#ifndef UDSTP_H
#define UDSTP_H

#include "candriver.h"
#include "qjsonobject.h"
#include "qtimer.h"
#include <cstdint>

#define TPLEN 1030

/*CAN/CAN FD define*/
typedef enum
{
    CANTP_STANDARD,  /*standard CAN*/
    CANTP_FD,        /*CAN FD*/
}tCANType;

typedef enum
{
    IDLE,           /*idle*/
    RX_SF,          /*wait signle frame*/
    RX_FF,          /*wait first frame*/
    RX_FC,          /*wait flow control frame*/
    RX_CF,          /*wait consective frame*/

    TX_SF,          /*tx signle frame*/
    TX_FF,          /*tx first frame*/
    TX_FC,          /*tx flow control*/
    TX_CF,          /*tx consective frame*/

    WAITTING_TX,    /*watting tx message*/

    WAIT_CONFIRM    /*wait confrim*/
}tCanTpWorkStatus;

typedef enum
{
    SF,             /*signle frame value*/
    FF,             /*first frame value*/
    CF,             /*consective frame value*/
    FC              /*flow control value*/
}tNetWorkFrameType;

typedef enum
{
    CONTINUE_TO_SEND, /*continue to send*/
    WAIT_FC,          /*wait flow control*/
    OVERFLOW_BUF      /*overflow buf*/
}tFlowStatus;

typedef enum{
    CANTP_TX_MSG_IDLE = 0,  /*CAN TP tx message idle*/
    CANTP_TX_MSG_SUCC,      /*CAN TP tx message successful*/
    CANTP_TX_MSG_FAIL,      /*CAN TP tx message fail*/
    CANTP_TX_MSG_WAITTING   /*CAN TP waitting tx message*/
}tCanTPTxMsgStatus;

typedef struct
{
    uint8_t ucSN;               /*SN*/
    uint8_t ucBlockSize;        /*Block size*/
    uint16_t xSTmin;            /*STmin*/
    uint16_t xMaxWatiTimeout;   /*timeout time*/
    uint32_t xCanTpId;          /*can tp message id*/
    bool isFinish;              /*can tp transfer finish*/
    bool isNeedTx;              /*can tp transfer finish*/
    uint16_t xPduDataLen;       /*pdu data len(Rx/Tx data len)*/
    uint16_t xPduDoneLen;       /*pdu done len(Rx/Tx done len)*/
    uint16_t xFFDataLen;        /*Rx/Tx FF data len*/
    uint16_t xCFNumber;         /*Rx/Tx CF number*/
    uint8_t aDataBuf[TPLEN];    /*Rx/Tx data buf*/
}tCanTpInfo;

#define IsSF(xNetWorkFrameType) ((((xNetWorkFrameType) >> 4u) ==  SF) ? TRUE : FALSE)
#define IsFF(xNetWorkFrameType) ((((xNetWorkFrameType) >> 4u) ==  FF) ? TRUE : FALSE)
#define IsCF(xNetWorkFrameType) ((((xNetWorkFrameType) >> 4u) ==  CF) ? TRUE : FALSE)
#define IsFC(xNetWorkFrameType) ((((xNetWorkFrameType) >> 4u) ==  FC) ? TRUE : FALSE)

class UdsTp : public QThread
{
    Q_OBJECT
public:
    UdsTp();
    void Initialization();
    static void DriverWriteAFrameInTP(const uint32_t i_RxID, const uint16_t i_RxDataLen, const uint8_t *i_pRxDataBuf);
    static bool DriverReadRespFormTP(uint32_t *i_RxID, uint16_t *i_RxDataLen, uint8_t *i_pRxDataBuf);
    static void DriverSetTxDataInTP(const uint32_t i_RxID, const uint16_t i_TxDataLen, const uint8_t *i_pTxDataBuf, const uint8_t *i_pExpectBuf);
    static uint32_t GetConfigTxPhyMsgID();
    static uint32_t GetConfigTxFunMsgID();
    static bool IsReceivedMsgIDValid(const uint32_t i_RxID);

private:
    void Tick1ms();
    void run();

signals:
    void updateTxMsg(sCANObj msg);

public:
    QJsonObject jsonTpInfor;
    bool bRunFlag = false;

private:
    QTimer TpTimer;
    static uint32_t xRxId;
    static uint32_t xTxPhyId;
    static uint32_t xTxFunId;
    static uint8_t gSTmin;
    tCANType eCanType = CANTP_STANDARD;
    static tCanTpWorkStatus gs_eCanTpWorkStatus;
    static tCanTpInfo gs_stCanTPTxDataInfo;    /*can tp tx data*/
    static tCanTpInfo gs_stCanTPRxDataInfo;    /*can tp rx data*/
    const uint8_t STmin = 1;
    const uint8_t BSize = 0;
};

#endif // UDSTP_H
